<template>
  <canvas :width="width" :height="height" ref="canvasRef"></canvas>
  <br />
  <button @click="onTran">平移-坐标系1</button>
  <br />
  <button @click="onTra2n">平移-坐标系2</button>
  <br />
  <button @click="onDrag">拖拽</button>
  <br />
  <button @click="onReset">复原</button>
</template>

<script setup lang="ts">
import { ref, onMounted, watch } from "vue";
import * as GLMatrix from "gl-matrix";
import { useBindDrag } from '../util/eleUtil'

const width = ref<number>(500);
const height = ref<number>(500);
const canvasRef = ref<HTMLCanvasElement>();
const glRef = ref<WebGLRenderingContext>();
const proRef = ref<WebGLProgram>();
const status = ref(5);
const { offset } = useBindDrag(canvasRef)
const offsetValue = ref<[number, number]>([0, 0])

onMounted(() => {
  init1();
  onRenderTri();
});

const delay = async () =>
  await new Promise((res) => setTimeout(() => res(null), 1000));

const init1 = () => {// 顶点着色器  偏移量为屏幕gl坐标系
  const gl = canvasRef.value?.getContext("webgl");
  if (!gl) return;
  gl.viewport(0, 0, width.value, height.value);
  const veString = `
    attribute vec4 a_position;
    uniform vec4 tran;// 平移量
    uniform mat4 viewPro;
    void main(void){
      gl_Position = viewPro * a_position + tran;
      gl_PointSize = 2.0;
    }
  `;
  const frString = `
    void main(void){
      gl_FragColor = vec4(1.0,1.0,0.0,1.0);
    }
  `;
  const veShader = gl.createShader(gl.VERTEX_SHADER);
  if (!veShader) return;
  gl.shaderSource(veShader, veString);
  gl.compileShader(veShader);

  if (!gl.getShaderParameter(veShader, gl.COMPILE_STATUS)) {
    throw new Error(gl.getShaderInfoLog(veShader) || "");
  }

  const frShader = gl.createShader(gl.FRAGMENT_SHADER);
  if (!frShader) return;
  gl.shaderSource(frShader, frString);
  gl.compileShader(frShader);

  const pro = gl.createProgram();
  if (!pro) return;
  gl.attachShader(pro, veShader);
  gl.attachShader(pro, frShader);
  gl.linkProgram(pro);
  gl.useProgram(pro);
  gl.clearColor(0, 0, 0, 1);
  gl.clear(gl.COLOR_BUFFER_BIT);

  glRef.value = gl;
  proRef.value = pro;
};

const init2 = () => { // 顶点着色器  偏移量为屏幕坐标系
  const gl = canvasRef.value?.getContext("webgl");
  if (!gl) return;
  gl.viewport(0, 0, width.value, height.value);

  const veString = `
    attribute vec4 a_position;
    uniform vec4 tran; // 平移量 向量
    uniform mat4 viewPro;
    void main(void){
      gl_Position = viewPro * (a_position + tran);
      gl_PointSize = 2.0;
    }
  `;

  const frString = `
    void main(void){
      gl_FragColor = vec4(1.0,1.0,0.0,1.0);
    }
  `;
  const veShader = gl.createShader(gl.VERTEX_SHADER);
  if (!veShader) return;
  gl.shaderSource(veShader, veString);
  gl.compileShader(veShader);

  if (!gl.getShaderParameter(veShader, gl.COMPILE_STATUS)) {
    throw new Error(gl.getShaderInfoLog(veShader) || "");
  }

  const frShader = gl.createShader(gl.FRAGMENT_SHADER);
  if (!frShader) return;
  gl.shaderSource(frShader, frString);
  gl.compileShader(frShader);

  const pro = gl.createProgram();
  if (!pro) return;
  gl.attachShader(pro, veShader);
  gl.attachShader(pro, frShader);
  gl.linkProgram(pro);
  gl.useProgram(pro);
  gl.clearColor(0, 0, 0, 1);
  gl.clear(gl.COLOR_BUFFER_BIT);

  glRef.value = gl;
  proRef.value = pro;
};

const onRenderTri = () => {
  if (!glRef.value) return;
  if (!proRef.value) return;
  const mat4 = GLMatrix.mat4.create();
  GLMatrix.mat4.ortho(mat4, 0, width.value, height.value, 0, -1, 1);
  const gl = glRef.value;
  const pro = proRef.value;
  const points = new Float32Array([250.0, 125, 125, 375, 375, 375]);
  const buffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  gl.bufferData(gl.ARRAY_BUFFER, points, gl.STATIC_DRAW);

  const a_position = gl.getAttribLocation(pro, "a_position");
  gl.enableVertexAttribArray(a_position);
  gl.vertexAttribPointer(a_position, 2, gl.FLOAT, true, 0, 0);

  const view = gl.getUniformLocation(pro, "viewPro");
  gl.uniformMatrix4fv(view, false, mat4);

  const tran = gl.getUniformLocation(pro, "tran");
  gl.uniform4f(tran, 0, 0, 0, 0.0);
  if (status.value === 1) {
    // 平移1 设置偏移位 gl坐标系 顶点着色器区别
    const tx = 0.5;
    const ty = 0.5;
    const tz = 0.0;
    gl.uniform4f(tran, tx, ty, tz, 0.0);
  } else if (status.value === 2) {
    // 平移2 设置点位屏幕坐标系 顶点着色器区别
    const tx = 125;
    const ty = -125;
    const tz = 0.0;
    gl.uniform4f(tran, tx, ty, tz, 0.0);
  } else if (status.value === 3) {
  } else if (status.value === 6) {
    if (offset.value) {
      const tx = offsetValue.value[0];
      const ty = offsetValue.value[1];
      const tz = 0.0;
      gl.uniform4f(tran, tx, ty, tz, 0.0);
    }
  }

  gl.clearColor(0, 0, 0, 1);
  gl.clear(gl.COLOR_BUFFER_BIT);

  gl.drawArrays(gl.TRIANGLES, 0, points.length / 2);
};


const onTran = async () => {
  if (status.value !== 5) {
    onReset();
    await delay();
  }
  status.value = 1;
  init1();
  onRenderTri();
};
const onTra2n = async () => {
  if (status.value !== 5) {
    onReset();
    await delay();
  }
  status.value = 2;
  init2();
  onRenderTri();
};

const onDrag = () => {
  onReset();
  status.value = 6;
  offsetValue.value = [0, 0]
  init2();
  onRenderTri();
}
const onReset = () => {
  status.value = 5;
  init1();
  onRenderTri();
};

watch(() => offset.value, () => {
  if (status.value === 6 && offset.value) {
    const [x, y] = offsetValue.value;
    const [_x, _y] = offset.value || [0, 0];
    offsetValue.value = [x + _x, y + _y]
    onRenderTri();
  }
})

</script>

<style></style>
